iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
DevOps

連DevSecOps都不知道怎麼發音怎麼開始學習?系列 第 7

Day.7 守門人升級:Python 多版本驗證(本地 tox × GitHub Actions Matrix)

  • 分享至 

  • xImage
  •  

昨天,我們設立了 Pull Request Flow 與 Branch protection rules
,確保任何程式碼進主分支前都得經過檢查與批准。

今天,我們要處理另一個經典問題:

「在我電腦能跑,不代表在你電腦能跑」

這句話不是藉口,而是一種古老的詛咒。它能讓任何 CI/CD pipeline 崩潰。為了打破這詛咒,我們引入兩個工具:

  • tox:本地多版本測試的神器
  • Matrix Build:CI 端平行跑不同 Python 版本,確保世界線一致

我們今天就是在打造一個「多重世界線的驗證機構」。如果岡部倫太郎有這工具,可能就不需要一直在各個世界線跑來跑去救真由理了。

1. 為什麼 DevSecOps 在意「多版本」?

DevOps 解決的是 持續交付 (CD) ,但 DevSecOps 還得顧慮 安全與穩定性

多版本測試的意義不只是「程式能不能跑」,還包含:

  • 依賴風險管理
    不同 Python 版本可能帶有不同套件依賴。沒測過的話,某版本可能暗藏漏洞或錯誤。

  • 避免版本漂移(Version Drift)
    「我環境能跑、你環境卻掛掉」的情況,通常源於環境差異。多版本測試能提早踩雷。

  • 合規要求
    金融、醫療等產業常有明確規範,要求系統能在特定版本下安全執行。

👉 想像《進擊的巨人》裡的各個城牆:
你不能只在「希娜之牆」測過,卻期望「瑪利亞之牆」也能同樣安全無虞。

2. 本地測試神器:tox

pip install tox

配置 tox.ini

[tox]
envlist = py310, py311, py312
skip_missing_interpreters = true

[testenv]
deps = -r requirements.txt
commands = pytest -q

執行

tox

會自動在 Python 3.10、3.11、3.12 上跑測試。

Windows系統如果要下載多版本Python,只要到官網(python.org)安裝加到path即可。

缺版本?它會跳過,但同時提醒你:「你的環境不完整,最好補齊」。

Q:我電腦只有一個 Python 版本,還需要 tox 嗎?
A:需要。因為 CI/CD 端會跑多版本,你最好先本地抓 bug,不然會變成 CI 一直報紅,心態會比世界線跳躍還崩潰。

3. 雲端測試:Matrix Build

tox 保護的是你的電腦世界線,但我們還要驗證「所有人的世界線」。

在 GitHub Actions 的 workflow 裡設定 Matrix Build

.github/workflows/ci.yml

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.10, 3.11, 3.12]

    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }} # 這段是要指定 Python版本
      - name: Install deps
        run: pip install -r requirements.txt
      - name: Run tests
        run: pytest -q

這樣,三條「平行世界線」會同時跑測試,全部通過才算過關。

Q:有 tox 還要 Matrix Build?
A:因為tox 保護的是「你的世界線」,而Matrix Build 保護的是「所有人的世界線」。

再搭配昨天(Day.6)的 Branch Protection Rules,就能強制要求 PR 必須通過所有 Python 版本的檢查。守門人從「有跑測試」進化為「所有世界線的測試都要通過」。

做到這裡,你的流程已經符合企業級 DevSecOps pipeline 的雛形

  • 本地 tox:快速發現問題,避免 CI 上才踩雷
  • CI Matrix Build:確保跨版本、跨環境一致性
  • Branch Protection:強制規範,守住主分支品質

這種設計,不只是穩定性,更是安全性的基礎。
因為一旦跨版本差異造成漏洞,攻擊者就能趁虛而入。
而我們的多世界線驗證,正是為了讓所有環境保持一致、防止破口。

在這邊整理一下目前的CI配置:

name: CI
on:
  push:
    branches: [ master ]   # 確認你的預設分支真的是 master;若是 main 要同步改
  pull_request:
    branches: [ master ]

# 最小權限 + 同分支只跑最新一次
permissions:
  contents: read
concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build:
    name: Test (${{ matrix.python-version }})
    runs-on: ubuntu-latest
    timeout-minutes: 15 #單個 job 最多跑 15 分鐘,超時會自動中止。
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.10", "3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }} # 這段是要指定 Python 版本
          cache: pip  # 直接用內建 pip 快取(會依 requirements* 與版本分開)

      - name: Install deps
        run: |
          python -m pip install --upgrade pip
          if [ -f requirements.txt ]; then python -m pip install -r requirements.txt; fi
          python -m pip install pytest flake8 black

      - name: Format check (black)
        run: python -m black --check .

      - name: Lint code
        run: python -m flake8 . --format=github # flake8 直接回饋到 PR(GitHub annotation)

      - name: Run tests 
        run: python -m pytest -q --maxfail=1 --disable-warnings --junitxml=pytest.xml
      - name: Upload test report 
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: pytest-report-${{ matrix.python-version }} 
          path: pytest.xml

除了之前寫的片段,還加入了一些功能提高效率和安全性

  • permissions: contents: read → 只給最小必要權限,減少安全風險。

  • concurrency → 保證同一個分支同時間只會跑 一個 workflow,舊的直接取消,避免資源浪費。

  • python -m flake8 . --format=github

    • 這是個 flake8 插件,可以把錯誤輸出成 GitHub Actions annotation 格式。
    • 這樣在 PR / commit 的 Files changed 頁面,會直接在程式碼行數旁邊顯示警告或錯誤,比純文字輸出更直觀。
  • pytest -q --maxfail=1 --disable-warnings --junitxml=pytest.xml

    • q 減少輸出
    • -maxfail=1 測一次錯誤就停
    • -disable-warnings 關掉 warning
    • -junitxml 產出報告檔 pytest.xml (在 GitHub Actions 頁面的 Artifacts 區塊下載,在這邊我寫只有 測試失敗 的時候才會被存成 artifact。)

4. 總結

今天,我們把 CI/CD 的測試邏輯拓展到「多世界線」:

  • tox:本地多版本測試,避免開發者自 high
  • Matrix Build:CI 平行驗證,保護團隊和生產環境
  • Branch Protection:與測試結果綁定,強化守門機制

這不只是為了讓開發流程更順暢,更是守住系統安全的關鍵。

就像岡部要確保所有世界線都能拯救真由理一樣,
我們要確保所有版本下,系統都能安全、穩定地存活。


上一篇
Day.6 世界線審判庭:Pull Request Flow 與守門人
下一篇
Day.8 從網工到 DevSecOps:用 Bandit 打造程式碼第一道防線
系列文
連DevSecOps都不知道怎麼發音怎麼開始學習?22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言